package settings

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/nicksnyder/go-i18n/v2/i18n"
	"golang.org/x/text/language"
)

var (
	AccessLangs []string
	Localizers  map[string]*i18n.Localizer
)

var (
	ErrInvalidLang  = errors.New("invalid language or language format")
	ErrNewLocalizer = errors.New("failed to create localized translator")
)

func NewI18nLocalizer(i18nDir string) error {
	files, err := os.ReadDir(i18nDir)
	if err != nil {
		return fmt.Errorf("failed to read directory, path=%s, err=%w", i18nDir, err)
	}
	for _, file := range files {
		if file.IsDir() {
			dirName := file.Name()
			filePath := filepath.Join(i18nDir, dirName)
			localizer, err := initLocalizer(dirName, filePath)
			if err != nil {
				return err
			}
			Localizers[dirName] = localizer
			AccessLangs = append(AccessLangs, dirName)
		}
	}
	return nil
}

func initLocalizer(lang string, path string) (*i18n.Localizer, error) {
	parts := strings.Split(lang, "-")
	if len(parts) == 0 || parts[0] == "" {
		return nil, ErrInvalidLang
	}
	languages, _, err := language.ParseAcceptLanguage(parts[0])
	if err != nil {
		return nil, fmt.Errorf("failed to parsing language: %w", err)
	}
	if len(languages) == 0 {
		return nil, ErrInvalidLang
	}
	langTag := languages[len(languages)-1]
	bundle := i18n.NewBundle(langTag)
	bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
	files, err := os.ReadDir(path)
	if err != nil {
		return nil, fmt.Errorf("failed to read directory, path=%s, err=%w", path, err)
	}
	for _, file := range files {
		if !strings.HasSuffix(file.Name(), ".toml") {
			continue
		}
		filePath := filepath.Join(path, file.Name())
		_, err = bundle.LoadMessageFile(filePath)
		if err != nil {
			return nil, fmt.Errorf("failed to load language file, path=%s, err=%w", filePath, err)
		}
	}
	localizer := i18n.NewLocalizer(bundle, lang)
	return localizer, nil
}

func TranslateWithLang(
	lang, msgID string,
	tmpData map[string]string,
) (string, error) {
	if msgID == "" {
		return "", fmt.Errorf("message ID is empty")
	}
	localizer := Localizers[lang]
	if localizer == nil {
		return msgID, fmt.Errorf("unsupported language types: %s", lang)
	}
	result, err := localizer.Localize(
		&i18n.LocalizeConfig{
			MessageID:    msgID,
			TemplateData: tmpData,
		},
	)
	if err != nil {
		return msgID, fmt.Errorf("failed to localize message: %w", err)
	}
	if result == "" {
		return msgID, nil
	}
	return result, nil
}
